﻿using System;
using System.Collections.Generic;
using System.Linq;
using static JoinBoxAlignPlug.CodeHelper;

namespace JoinBoxAlignPlug
{
    public partial class ChangTextAlignment
    {
        /// <summary>
        /// 上下行符号连续
        /// </summary>
        /// <param name="one">连续的第一行</param>
        /// <param name="fuhaoIndex">传入连续的第一行符号长度,返回记录最大行长度</param>
        /// <returns>记录哪些行连续</returns>
        void IsContinuousForTwoPlus(int one, ref int fuhaoIndex, List<int> hangList)
        {
            //又有代码又有注释的
            int numLine = one;//记录其后连续的多少行有符号
            while (numLine < _strs.Length)
            {
                Console.WriteLine("符号是://行数是" + numLine);

                var code2 = GetCode(_strs[numLine]);
                if (code2.Length == 0)//纯注释行跳过
                    break;

                var fuhaos = new List<int>();
                GetFuhaoIndex(_strs[numLine], _annotation, fuhaos);

                //中断:不含有符号,表示上下行非连续出现符号
                if (fuhaos.Count == 0)
                    break;

                GetText2FuhaoLenth(Encoding, _strs[numLine], fuhaos[0], ref fuhaoIndex);
                hangList.Add(numLine);
                ++numLine;
            }
            // 如果是一个,对齐也没有意义
            if (hangList.Count == 1)
                hangList.Clear();
        }

        /// <summary>
        /// 包围范围
        /// </summary>
        /// <param name="left">搜索的符号上部分,例如大括号{</param>
        /// <param name="right">搜索的符号下部分,例如大括号}</param>
        /// <param name="one">要搜索的代码行第一行</param>
        /// <param name="up">上部分行数,没找到大括号-1</param>
        /// <param name="down">下部分行数</param>
        /// <param name="repeat">记录大括号重复</param>
        void GetCurlyBracesInternal(string left, string right, int one,
            out int up, out int down, Dictionary<int, int> repeat)
        {
            var num = new List<int>();

            // 输入的one是含有=号的
            string nCode;

            //往上搜索,先搜本行
            int kuoHao = 0;
            up = one;
            while (up > 0)
            {
                nCode = GetCode(_strs[up]);

                num.Clear();
                GetFuhaoIndex(nCode, right, num);
                kuoHao -= num.Count;//发现闭号

                num.Clear();
                GetFuhaoIndex(nCode, left, num);
                kuoHao += num.Count; //发现开号

                if (kuoHao == 1) //往下搜索了
                    break;
                --up;
            }

            // 没有找到开号,例如 using引入文件有=号
            if (kuoHao != 1)
            {
                up = -1;
                down = -1;
                return;
            }

            //重复的话,直接返回
            if (repeat.Keys.Contains(up))
            {
                down = repeat[up];
                return;
            }

            //往下搜索
            down = one + 1;
            while (down < _strs.Length)
            {
                nCode = GetCode(_strs[down]);

                num.Clear();
                GetFuhaoIndex(nCode, left, num);
                kuoHao += num.Count; //发现开号

                num.Clear();
                GetFuhaoIndex(nCode, right, num);
                kuoHao -= num.Count; //发现闭号

                if (kuoHao == 0)
                    break;
                ++down;
            }

            //没有找到闭号
            if (down == _strs.Length)
                down = -1;
        }

        /// <summary>
        /// 大括号内的连续,就是要对齐的行
        /// </summary>
        /// <param name="fuhao">需要对齐的符号:注释/等号</param>
        /// <param name="one">这行,必然有这样的符号</param>
        /// <param name="fuhaoPosition">符号出现的位置</param>
        /// <param name="hangList">返回大括号内所有行号,每行内容并不是都含有注释符号,因为它不是过滤的,而是全选大括号内的</param>
        /// <param name="repeat">记录大括号重复</param>
        /// <returns>返回down,但是不能给外面跳到大括号闭号位置,因为类中的属性可能有=号,而类中的构造函数=号连续,会造成无法判断构造函数的问题,所以此值无用</returns>
        int IsContinuousForCurlyBraces(string fuhao, int one, ref int fuhaoPosition,
            List<int> hangList,
            Dictionary<int, int> repeat)
        {
            GetCurlyBracesInternal(_curlyBracesLeft, _curlyBracesRight, one,
                out int up, out int down, repeat);

            if (up == -1 || down == -1)//没有找到大括号
                return one;
            if (repeat.Keys.Contains(up))//大括号重复判断
                return one;
            repeat.Add(up, down);

            Console.WriteLine("符号是:" + fuhao + " one:" + one + " up:" + up + " down:" + down);

            //enum豁免规则:因为enum在大括号内可能存在用位运算符|换行累加,所以enum的括号内都需要对齐
            var isEnumClass = IsEnumClass(up);

            bool lainXuFlag = true;                              //连续的记号
            for (int numLine = up; numLine < down + 1; numLine++)//从大括号行开始,它可能就是代码行
            {
                hangList.Add(numLine);

                //以下跳过表示:大括号内为连续
                //跳过:注释行// 预处理行#
                if (string.IsNullOrEmpty(GetCode(_strs[numLine])))
                    continue;

                // GetValidCode 注意此处[获取/设置]部分相同,所以如果修改,需要两边同步.
                var fuhaos = new List<int>();
                var validCode = GetValidCode(fuhao, numLine, down + 1, out int jumpComment, fuhaos);
                if (numLine == jumpComment)//没有多行注释,也就一行解决的
                {
                    if (validCode == null)//没有有效代码部分
                        continue;
                    if (numLine == down || numLine == down - 1)//大括号行或者上一行
                    {
                        var str = validCode[0].Trim().Replace(";", string.Empty);
                        if (ReservedWord.Contains(str))//跳过最后那行的关键字
                            continue;
                    }
                    if (fuhaos.Count == 0 &&  //跳过:不含有符号
                         isEnumClass == -1 && //枚举类全部认定为连续的
                         numLine != up &&     //括号行
                         numLine != down)     //括号行
                    {
                        lainXuFlag = false;
                        break;
                    }
                }

                //跳过:不含有符号
                //多行注释上面的第一行如果有符号也要处理
                if (fuhaos.Count != 0)
                    GetText2FuhaoLenth(Encoding, _strs[numLine], fuhaos[0], ref fuhaoPosition);

                //跳过:多行注释开闭号  开号/* 闭号*/
                if (numLine != jumpComment)
                {
                    for (int i = numLine; i < jumpComment + 1; i++)//补充一个自增1
                        hangList.Add(i + 1);                       //跳过的行加入
                    numLine = jumpComment;
                    continue;
                }
            }

            if (!lainXuFlag)
            {
                hangList.Clear();
            }
            else
            {
                var hangList2 = new List<int>(hangList);//复制一份过去
                hangList2 = hangList2.Distinct().ToList();
                hangList.Clear();
                hangList.AddRange(hangList2);
            }
            return down;
        }

        /// <summary>
        /// 跳过段落注释
        /// </summary>
        /// <param name="numLine">找/*的行</param>
        /// <param name="lastLine">括号}的范围</param>
        /// <returns>跳到哪一行</returns>
        int JumpComments(int numLine, int lastLine)
        {
            int jilukaibi = numLine;
            var zsf_kai = new List<int>();
            GetFuhaoIndex(_strs[numLine], _annotationLeft, zsf_kai);

            if (zsf_kai.Count != 0)//如果找到了
            {
                //判断前面是否存在//将/*无效化了
                var qian = _strs[numLine].Substring(0, zsf_kai[0]);
                var tete = new List<int>();
                GetFuhaoIndex(qian, _annotation, tete);
                if (tete.Count != 0)
                    return numLine;//原地跳

                //遍历本行和之后的,因为本行可能就是有*/
                for (int numLine2 = numLine; numLine2 < lastLine; numLine2++)
                {
                    var zsf_bi = _strs[numLine2].IndexOf(_annotationRight);//注释符*/即使是字符串内也可识别的
                    if (zsf_bi != -1)                                      //找到闭号
                    {
                        if (numLine2 == numLine)//开号和闭号同一行
                            jilukaibi = numLine;
                        break;
                    }
                    ++jilukaibi;//跳过行增加
                }
            }
            return jilukaibi;
        }

        /// <summary>
        /// 判断是不是枚举类,括号行向上搜索
        /// </summary>
        /// <param name="numLine"></param>
        /// <returns>失败-1,成功返回enum的定义行</returns>
        int IsEnumClass(int numLine)
        {
            int ok = -1;
            //往上搜索
            var up = numLine;
            while (up > 0)//上一行
            {
                var code = GetCode(_strs[up]);
                if (string.IsNullOrEmpty(code))
                {
                    --up;
                    continue;
                }
                //有效行,如果不含有就结束掉它,以免往上一直搜
                var sps = code.Split(' ');
                foreach (var item in sps)
                {
                    if (item == _enum)
                        return up;
                }

                //判断是不是{行,如果是的话,就往上跳
                var rightNum = new List<int>();
                GetFuhaoIndex(code, _curlyBracesLeft, rightNum);
                if (rightNum.Count != 0)
                {
                    --up;
                    continue;
                }

                break;// 有效行,直接结束
            }
            return ok;
        }
    }
}
